import { Byte } from '../../api/io/Byte';
import { ITimer } from '../../api/timer/ITimer';
import { IAsync } from '../../api/event/IAsync';



/**宠物属性枚举*/
export const enum E_Pet {
	/**宠物id*/
	PET_ID = 0,
	/**锁定*/
	LOCK = 1,
	/**上阵位置 >0, == 0-没有上阵*/
	FIGHT_POS = 2,
	/**竞技场阵位 >0, == 0-没有上阵*/
	ARENA_POS = 3,
	/**品质*/
	QUALITY = 4,
	/**配置表id*/
	CONFIG_ID = 5,
	/**宠物等级*/
	PET_LEVEL = 6,
	/**觉醒等级*/
	WAKE_LEVEL = 7,
	/**进阶等级*/
	EVOLUTION_LEVEL = 8,
	/**技能符文4*/
	RUNE4 = 9,
	/**技能符文5*/
	RUNE5 = 10,
	/**枚举数量*/
	EnumCount = 11
}


/**宠物*/
export class Pet {
	/**事件ID*/
	public static readonly EVENT_ID = 'STRUCT_DATA_PET_EVENT_ID';
	/**整体更新事件ID（部分只需要监听整体变化）*/
	public static readonly TOTAL_EVENT_ID = 'STRUCT_DATA_PET_TOTAL_EVENT_ID';
	/**缓存池*/
	private static POOL: Pet[] = [];

	/**创建入口*/
	public static create(json?: string): Pet {
		const c = this.POOL.pop() || new Pet();
		c._destroyed = false;
		c.resetProperty();
		if (json) {
			c.parse(json);
		}
		return c;
	}


	/**已释放*/
	protected _destroyed = false;
	/**宠物id (uint32)*/
	protected _petId: number;
	/**锁定*/
	protected _lock: boolean;
	/**上阵位置 >0, == 0-没有上阵 (int8)*/
	protected _fightPos: number;
	/**竞技场阵位 >0, == 0-没有上阵 (int8)*/
	protected _arenaPos: number;
	/**品质 (uint8)*/
	protected _quality: number;
	/**配置表id (uint32)*/
	protected _configId: number;
	/**宠物等级 (uint16)*/
	protected _petLevel: number;
	/**觉醒等级 (uint16)*/
	protected _wakeLevel: number;
	/**进阶等级 (uint16)*/
	protected _evolutionLevel: number;
	/**技能符文4 (uint32)*/
	protected _rune4: number;
	/**技能符文5 (uint32)*/
	protected _rune5: number;


	/**构建函数-私有，防止外部创建*/
	private constructor() {
	}


	/**释放*/
	public destroy(): void {
		if (this._destroyed) {
			return;
		}
		this._destroyed = true;
		this.resetProperty(true);
		if (Pet.POOL.indexOf(this) === -1) {
			Pet.POOL.push(this);
		}
	}

	/**宠物id*/
	public get petId() {
		return this._petId;
	}


	/**宠物id*/
	public set petId(v: number) {
		this._petId = v;
	}


	/**锁定*/
	public get lock() {
		return this._lock;
	}


	/**锁定*/
	public set lock(v: boolean) {
		this._lock = v;
	}


	/**上阵位置 >0, == 0-没有上阵*/
	public get fightPos() {
		return this._fightPos;
	}


	/**上阵位置 >0, == 0-没有上阵*/
	public set fightPos(v: number) {
		this._fightPos = v;
	}


	/**竞技场阵位 >0, == 0-没有上阵*/
	public get arenaPos() {
		return this._arenaPos;
	}


	/**竞技场阵位 >0, == 0-没有上阵*/
	public set arenaPos(v: number) {
		this._arenaPos = v;
	}


	/**品质*/
	public get quality() {
		return this._quality;
	}


	/**品质*/
	public set quality(v: number) {
		this._quality = v;
	}


	/**配置表id*/
	public get configId() {
		return this._configId;
	}


	/**配置表id*/
	public set configId(v: number) {
		this._configId = v;
	}


	/**宠物等级*/
	public get petLevel() {
		return this._petLevel;
	}


	/**宠物等级*/
	public set petLevel(v: number) {
		this._petLevel = v;
	}


	/**觉醒等级*/
	public get wakeLevel() {
		return this._wakeLevel;
	}


	/**觉醒等级*/
	public set wakeLevel(v: number) {
		this._wakeLevel = v;
	}


	/**进阶等级*/
	public get evolutionLevel() {
		return this._evolutionLevel;
	}


	/**进阶等级*/
	public set evolutionLevel(v: number) {
		this._evolutionLevel = v;
	}


	/**技能符文4*/
	public get rune4() {
		return this._rune4;
	}


	/**技能符文4*/
	public set rune4(v: number) {
		this._rune4 = v;
	}


	/**技能符文5*/
	public get rune5() {
		return this._rune5;
	}


	/**技能符文5*/
	public set rune5(v: number) {
		this._rune5 = v;
	}



	/**通过枚举获取值*/
	public getV(k: E_Pet): any {
		switch (k) {
			case E_Pet.PET_ID: return this._petId;
			case E_Pet.LOCK: return this._lock;
			case E_Pet.FIGHT_POS: return this._fightPos;
			case E_Pet.ARENA_POS: return this._arenaPos;
			case E_Pet.QUALITY: return this._quality;
			case E_Pet.CONFIG_ID: return this._configId;
			case E_Pet.PET_LEVEL: return this._petLevel;
			case E_Pet.WAKE_LEVEL: return this._wakeLevel;
			case E_Pet.EVOLUTION_LEVEL: return this._evolutionLevel;
			case E_Pet.RUNE4: return this._rune4;
			case E_Pet.RUNE5: return this._rune5;
			default: return null;
		}
	}


	/**通过枚举设置值*/
	public setV(k: E_Pet, v: any): void {
		switch (k) {
			case E_Pet.PET_ID: this._petId = v; break;
			case E_Pet.LOCK: this._lock = v; break;
			case E_Pet.FIGHT_POS: this._fightPos = v; break;
			case E_Pet.ARENA_POS: this._arenaPos = v; break;
			case E_Pet.QUALITY: this._quality = v; break;
			case E_Pet.CONFIG_ID: this._configId = v; break;
			case E_Pet.PET_LEVEL: this._petLevel = v; break;
			case E_Pet.WAKE_LEVEL: this._wakeLevel = v; break;
			case E_Pet.EVOLUTION_LEVEL: this._evolutionLevel = v; break;
			case E_Pet.RUNE4: this._rune4 = v; break;
			case E_Pet.RUNE5: this._rune5 = v; break;
			default: break;
		}
	}


	/**初始化*/
	public resetProperty(fromDestroy = false): void {
		//宠物id
		this._petId = 0;
		//锁定
		this._lock = false;
		//上阵位置 >0, == 0-没有上阵
		this._fightPos = 0;
		//竞技场阵位 >0, == 0-没有上阵
		this._arenaPos = 0;
		//品质
		this._quality = 0;
		//配置表id
		this._configId = 0;
		//宠物等级
		this._petLevel = 0;
		//觉醒等级
		this._wakeLevel = 0;
		//进阶等级
		this._evolutionLevel = 0;
		//技能符文4
		this._rune4 = 0;
		//技能符文5
		this._rune5 = 0;
	}


	/**序列化*/
	public stringify(toString: boolean): string | any {
		const json: any = {};
		if (this._petId) {
			json.petId = this._petId;
		}
		if (this._lock) {
			json.lock = this._lock;
		}
		if (this._fightPos) {
			json.fightPos = this._fightPos;
		}
		if (this._arenaPos) {
			json.arenaPos = this._arenaPos;
		}
		if (this._quality) {
			json.quality = this._quality;
		}
		if (this._configId) {
			json.configId = this._configId;
		}
		if (this._petLevel) {
			json.petLevel = this._petLevel;
		}
		if (this._wakeLevel) {
			json.wakeLevel = this._wakeLevel;
		}
		if (this._evolutionLevel) {
			json.evolutionLevel = this._evolutionLevel;
		}
		if (this._rune4) {
			json.rune4 = this._rune4;
		}
		if (this._rune5) {
			json.rune5 = this._rune5;
		}

		return toString ? JSON.stringify(json) : json;
	}


	/**反序列化*/
	public parse(jsonv: string | any): this {
		this.resetProperty();
		if (!jsonv) {
			return this;
		}
		const json = typeof (jsonv) === 'string' ? JSON.parse(jsonv) : jsonv;
		if (json.petId) {
			this._petId = json.petId;
		}
		if (json.lock) {
			this._lock = json.lock;
		}
		if (json.fightPos) {
			this._fightPos = json.fightPos;
		}
		if (json.arenaPos) {
			this._arenaPos = json.arenaPos;
		}
		if (json.quality) {
			this._quality = json.quality;
		}
		if (json.configId) {
			this._configId = json.configId;
		}
		if (json.petLevel) {
			this._petLevel = json.petLevel;
		}
		if (json.wakeLevel) {
			this._wakeLevel = json.wakeLevel;
		}
		if (json.evolutionLevel) {
			this._evolutionLevel = json.evolutionLevel;
		}
		if (json.rune4) {
			this._rune4 = json.rune4;
		}
		if (json.rune5) {
			this._rune5 = json.rune5;
		}
		return this;
	}


	/**序列化-二进制*/
	public toBytes(byte: Byte): void {
		if (!byte) {
			return;
		}
		byte.writeUint32(this._petId);
		byte.writeBool(this._lock);
		byte.writeInt8(this._fightPos);
		byte.writeInt8(this._arenaPos);
		byte.writeUint8(this._quality);
		byte.writeUint32(this._configId);
		byte.writeUint16(this._petLevel);
		byte.writeUint16(this._wakeLevel);
		byte.writeUint16(this._evolutionLevel);
		byte.writeUint32(this._rune4);
		byte.writeUint32(this._rune5);
	}


	/**反序列化-二进制*/
	public fromBytes(byte: Byte): this {
		this.resetProperty();
		if (!byte) {
			return;
		}
		this._petId = byte.readUint32();
		this._lock = byte.readBool();
		this._fightPos = byte.readInt8();
		this._arenaPos = byte.readInt8();
		this._quality = byte.readUint8();
		this._configId = byte.readUint32();
		this._petLevel = byte.readUint16();
		this._wakeLevel = byte.readUint16();
		this._evolutionLevel = byte.readUint16();
		this._rune4 = byte.readUint32();
		this._rune5 = byte.readUint32();
		return this;
	}


	/**克隆*/
	public clone(): Pet {
		const byte = Byte.createFromPool();
		this.toBytes(byte);
		byte.pos = 0;
		const clonev = Pet.create().fromBytes(byte);
		Byte.recoverToPool(byte);
		return clonev;
	}


	/**处理更新*/
	public processUpdate(jsonv: string): void {
		if (!jsonv) {
			return;
		}

		const eventID = Pet.EVENT_ID;
		const us = JSON.parse(jsonv);

		for (let i = 0, len = us.length; i < len;) {
			const idx = us[i];
			//宠物id
			if (idx === E_Pet.PET_ID) {
				const oldv = this._petId;
				this._petId = us[i + 1];
				IAsync.dispatch(eventID, idx, this._petId, oldv);
				i += 2;
				continue;
			}
			//锁定
			if (idx === E_Pet.LOCK) {
				const oldv = this._lock;
				this._lock = us[i + 1];
				IAsync.dispatch(eventID, idx, this._lock, oldv);
				i += 2;
				continue;
			}
			//上阵位置 >0, == 0-没有上阵
			if (idx === E_Pet.FIGHT_POS) {
				const oldv = this._fightPos;
				this._fightPos = us[i + 1];
				IAsync.dispatch(eventID, idx, this._fightPos, oldv);
				i += 2;
				continue;
			}
			//竞技场阵位 >0, == 0-没有上阵
			if (idx === E_Pet.ARENA_POS) {
				const oldv = this._arenaPos;
				this._arenaPos = us[i + 1];
				IAsync.dispatch(eventID, idx, this._arenaPos, oldv);
				i += 2;
				continue;
			}
			//品质
			if (idx === E_Pet.QUALITY) {
				const oldv = this._quality;
				this._quality = us[i + 1];
				IAsync.dispatch(eventID, idx, this._quality, oldv);
				i += 2;
				continue;
			}
			//配置表id
			if (idx === E_Pet.CONFIG_ID) {
				const oldv = this._configId;
				this._configId = us[i + 1];
				IAsync.dispatch(eventID, idx, this._configId, oldv);
				i += 2;
				continue;
			}
			//宠物等级
			if (idx === E_Pet.PET_LEVEL) {
				const oldv = this._petLevel;
				this._petLevel = us[i + 1];
				IAsync.dispatch(eventID, idx, this._petLevel, oldv);
				i += 2;
				continue;
			}
			//觉醒等级
			if (idx === E_Pet.WAKE_LEVEL) {
				const oldv = this._wakeLevel;
				this._wakeLevel = us[i + 1];
				IAsync.dispatch(eventID, idx, this._wakeLevel, oldv);
				i += 2;
				continue;
			}
			//进阶等级
			if (idx === E_Pet.EVOLUTION_LEVEL) {
				const oldv = this._evolutionLevel;
				this._evolutionLevel = us[i + 1];
				IAsync.dispatch(eventID, idx, this._evolutionLevel, oldv);
				i += 2;
				continue;
			}
			//技能符文4
			if (idx === E_Pet.RUNE4) {
				const oldv = this._rune4;
				this._rune4 = us[i + 1];
				IAsync.dispatch(eventID, idx, this._rune4, oldv);
				i += 2;
				continue;
			}
			//技能符文5
			if (idx === E_Pet.RUNE5) {
				const oldv = this._rune5;
				this._rune5 = us[i + 1];
				IAsync.dispatch(eventID, idx, this._rune5, oldv);
				i += 2;
				continue;
			}

			console.error('[Struct Data] can not find enum in Pet with idx = ' + idx + ', version maybe wrong.')
		}

		//全更事件
		ITimer.callLater(this, this.dispatchTotalUpdate);
	}


	/**比对不一致结果*/
	public getCompareInfo(other: Pet): string {
		if (!other) {
			return null;
		}

		const updates: any[] = [];

		if (this._petId !== other._petId) {
			updates.push(E_Pet.PET_ID, this._petId);
		}
		if (this._lock !== other._lock) {
			updates.push(E_Pet.LOCK, this._lock);
		}
		if (this._fightPos !== other._fightPos) {
			updates.push(E_Pet.FIGHT_POS, this._fightPos);
		}
		if (this._arenaPos !== other._arenaPos) {
			updates.push(E_Pet.ARENA_POS, this._arenaPos);
		}
		if (this._quality !== other._quality) {
			updates.push(E_Pet.QUALITY, this._quality);
		}
		if (this._configId !== other._configId) {
			updates.push(E_Pet.CONFIG_ID, this._configId);
		}
		if (this._petLevel !== other._petLevel) {
			updates.push(E_Pet.PET_LEVEL, this._petLevel);
		}
		if (this._wakeLevel !== other._wakeLevel) {
			updates.push(E_Pet.WAKE_LEVEL, this._wakeLevel);
		}
		if (this._evolutionLevel !== other._evolutionLevel) {
			updates.push(E_Pet.EVOLUTION_LEVEL, this._evolutionLevel);
		}
		if (this._rune4 !== other._rune4) {
			updates.push(E_Pet.RUNE4, this._rune4);
		}
		if (this._rune5 !== other._rune5) {
			updates.push(E_Pet.RUNE5, this._rune5);
		}

		const jsonv = updates.length === 0 ? null : JSON.stringify(updates);
		return jsonv;
	}


	/**全部更新*/
	protected dispatchTotalUpdate(): void {
		IAsync.dispatch(Pet.TOTAL_EVENT_ID, this.getV(0));
	}

}
